#!/usr/bin/env python3# -*- coding: utf-8 -*-"""固定 Windows 路径版：脚本内直接写死 hardtest 的绝对路径，运行即解出明文/flag。无需命令行参数。若文件路径变化，请改 PATH_BIN 变量。"""from pathlib import Path # === 固定的 Windows 二进制路径（按你的要求写死） ===PATH_BIN = Path(r"C:\\Users\\Jiker\\Downloads\\8486c393ef8744a2989e60540644c788\\hardtest") # 题面贴出的 byte_2120 常量（24 字节）
from pathlib import Path
PATH_BIN = Path("./hardtest")
BYTE_2120 = bytes([    0x97,0xD5,0x60,0x43,0xB4,0x10,0x43,0x73,0x0F,0xDA,    0x43,0xCD,0xD3,0xE8,0x73,0x4A,0x94,0xC3,0xCD,0x71,    0xBD,0xDC,0x97,0x1A]) 
def rol8(x: int, r: int) -> int:    
    r &= 7    
    x &= 0xFF    
    return ((x << r) | (x >> (8 - r))) & 0xFF
def ror8(x: int, r: int) -> int:    
    r &= 7    
    x &= 0xFF    
    return ((x >> r) | (x << (8 - r))) & 0xFF
def inv_nibble_affine(w: int) -> int:    
    """    半字节线性变换逆：高半字节乘 11（3 的逆），低半字节乘 13（5 的逆），模 16。    """    
    w &= 0xFF    
    h = (w >> 4) & 0xF    
    l = w & 0xF    
    h0 = (11 * h) & 0xF    
    l0 = (13 * l) & 0xF    
    return ((h0 << 4) | l0) & 0xFF 
def inv_mod257(x: int) -> int:    
    """    sub_1313 的逆：x -> x^255 mod 257（x=0 则仍为 0）。    """    
    if x == 0:        return 0    
    return pow(x, 255, 257) 
def extract_tables(bin_bytes: bytes):   
     """    在二进制中定位 byte_2120（已知 24 字节常量），并取其前 0x100 字节为 S-box(byte_2020)。    """    
     pos = bin_bytes.find(BYTE_2120)    
     if pos == -1:        raise RuntimeError("未在二进制里找到 byte_2120 固定序列；请确认文件是否匹配本题。")    
     if pos < 0x100:        raise RuntimeError("byte_2120 之前不足 0x100 字节，无法提取 S-box。")    
     sbox = bin_bytes[pos-0x100:pos]    
     if len(sbox) != 256 or len(set(sbox)) != 256:        
        raise RuntimeError("提取到的 S-box 不是 256 个互异字节，可能偏移不对。")    
     return sbox, BYTE_2120 
def recover_flag(bin_path: Path) -> bytes:
    data = bin_path.read_bytes()
    sbox, target =extract_tables(data)
    inv_sbox ={sbox[i]:i for i in range(256)} #逆查
    out =[]
    for i,y in enumerate(target):
#y=byte 2020[ sub 12DE(v6，2)]撻蜊砂芝荻侉贽肆玟
        idx= inv_sbox[y]
        v6 =rol8(idx,2)
        z = inv_mod257(v6) & 0xFF
        v4 = inv_nibble_affine(z)
        a1 = ror8(v4,3) ^ 0x5A
        print(a1,end=',')
        k = (i%7)+1
        s_i = ror8(a1,k)
        out.append(s_i)
    return bytes(out)
#idx = ROR8(v6,2)#v6= ROL8(idx,2)
#v6=sub 1313(z)=>z=inv_mod257(v6)z=inv mod257(v6)& xFF
#z=affine( v4)=>v4= inv nibble affine(z)v4 = inv nibble affine(z)
#v4=sub 12A9(a1 ^0x5A,3)=ROL8(a1 ^ 0x5A, 3)a1 =ror8(v4，3)^0x5A
#a1=sub 12A9(s[i],(i%7)+1)= ROL8(s[i],k)k=(i%7)+1
def main():
    if not PATH_BIN.exists():
        raise SystemExit(f"错误：文件不存在：{PATH_BIN}")
    flag_bytes = recover_flag(PATH_BIN)
    try:
        flag_str = flag_bytes.decode("utf-8")
    except UnicodeDecodeError:
        flag_str = flag_bytes.decode("latin1")
    print("[+] 恢复明文：", flag_str)
    if not (flag_str.startswith("flag{") and flag_str.endswith("}")):
        print("[i] 如需标准 flag 形式，可使用：flag{" + flag_str + "}")
main()